package com.sport.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.sport.entity.SysUser;
import com.sport.service.SysUserService;
import com.sport.utils.PasswordUtils;
import com.sport.utils.QRCodeUtils;
import com.sport.model.Result;
import io.swagger.v3.oas.annotations.Operation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.web.client.RestTemplate;

@SaIgnore
@RestController
@RequestMapping("/login")
public class WxController {

    private static final Logger logger = LoggerFactory.getLogger(WxController.class);

    @Autowired
    private SysUserService userService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @SaIgnore
    @GetMapping("/generateQRCode")
    @Operation(summary = "生成微信登录二维码")
    public ResponseEntity<byte[]> generateQRCode() {
        try {
            String uuid = UUID.randomUUID().toString();
            // 微信 OAuth2 授权 URL
            String appId = "wxd7cb0b6088587400"; // 你的微信小程序或公众号的 AppID
            String redirectUri = "http://tqku4v.natappfree.cc/login/wechatCallback"; // 你的回调 URL，需要 URL 编码
            String scope = "snsapi_userinfo"; // 或者 "snsapi_userinfo" 如果需要用户信息
            String state = uuid; // 使用 UUID 作为 state 参数

            String qrCodeContent = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appId +
                                 "&redirect_uri=" + redirectUri +
                                 "&response_type=code&scope=" + scope +
                                 "&state=" + state +
                                 "#wechat_redirect";

            // 生成 BitMatrix
            BitMatrix bitMatrix = QRCodeUtils.generateQRCodeBitMatrix(qrCodeContent);

            // 将 BitMatrix 转换为字节数组
            ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream();
            MatrixToImageWriter.writeToStream(bitMatrix, "PNG", pngOutputStream);
            byte[] pngData = pngOutputStream.toByteArray();

            redisTemplate.opsForValue().set("qrCode:" + uuid, "pending", 5, TimeUnit.MINUTES);
//            logger.info("Stored UUID in Redis: qrCode:{}", uuid); // 添加日志
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.IMAGE_PNG);
            headers.set("x-uuid", uuid); // 添加 UUID 到响应头

            // 添加日志验证响应头
//            logger.info("Setting response header x-uuid: {}", uuid);

            return new ResponseEntity<>(pngData, headers, HttpStatus.OK);
        } catch (WriterException | IOException e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
        }
    }



    @SaIgnore
    @GetMapping("/wechatCallback")
    @Operation(summary = "微信授权回调")
    public Result<String> wechatCallback(@RequestParam String code, @RequestParam String state) {
        if (code == null || code.isEmpty()) {
//            logger.error("Code is missing or empty");
            return Result.error("微信授权回调处理失败: 缺少 code 参数");
        }

        try {
            // 使用 code 获取 access_token 和 openid
            String appId = "wxd7cb0b6088587400"; // 你的微信小程序或公众号的 AppID
            String appSecret = "e5fcf3fa92ca73ff611da187d0482807"; // 你的微信小程序或公众号的 AppSecret
            String accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId +
                                  "&secret=" + appSecret +
                                  "&code=" + code +
                                  "&grant_type=authorization_code";

            // 打印请求参数
//            logger.info("AppID: {}, Secret: {}, Code: {}", appId, appSecret, code);

            // 发送 HTTP 请求获取 access_token 和 openid
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> response = restTemplate.getForEntity(accessTokenUrl, String.class);
            String responseBody = response.getBody();

            // 打印微信服务器响应
//            logger.info("WeChat Server Response: {}", responseBody);

            // 解析 JSON 响应
            ObjectMapper objectMapper = new ObjectMapper();
            Map<String, Object> responseMap = objectMapper.readValue(responseBody, new TypeReference<HashMap<String, Object>>() {});

            // 打印解析后的响应
//            logger.info("Parsed Response Map: {}", responseMap);

            String openid = (String) responseMap.get("openid");

            if (openid == null || openid.isEmpty()) {
//                logger.error("OpenID is null or empty in response map: {}", responseMap);
                return Result.error("微信授权回调处理失败: OpenID 为空");
            }

            // 添加日志记录
//            logger.info("Received code: {}, state: {}, openid: {}", code, state, openid);

            // 调用 simulateUserScan 接口
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
            map.add("uuid", state);
            map.add("openid", openid);

            HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
            ResponseEntity<String> result = restTemplate.postForEntity("http://tqku4v.natappfree.cc/login/simulateUserScan", request, String.class);

            return Result.success(result.getBody());
        } catch (Exception e) {
//            logger.error("Error processing WeChat callback", e);
            return Result.error("微信授权回调处理失败: " + e.getMessage());
        }
    }




    @SaIgnore
    @GetMapping("/checkQRCodeStatus")
    @Operation(summary = "检查二维码状态")
    public Result<Map<String, String>> checkQRCodeStatus(@RequestParam String uuid) {
        String status = redisTemplate.opsForValue().get("qrCode:" + uuid);
//        logger.info("Checking QR Code Status for UUID: {}, Status: {}", uuid, status); // 添加日志
        if ("pending".equals(status)) {
            Map<String, String> data = new HashMap<>();
            data.put("data", "pending");
            return Result.success("等待用户扫描", data);
        } else if ("success".equals(status)) {
            // 获取用户ID
            Long userId = Long.parseLong(redisTemplate.opsForValue().get("qrCodeUserId:" + uuid));
            // 生成Token
            StpUtil.login(userId, "wx");
            Map<String, String> map = new HashMap<>();
            cn.dev33.satoken.stp.SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            map.put("tokenHead", tokenInfo.getTokenName());
            map.put("token", tokenInfo.getTokenValue());
            return Result.success(map);
        } else {
            return Result.success("二维码已过期或无效");
        }
    }

    @SaIgnore
    @PostMapping("/simulateUserScan")
    @Operation(summary = "用户微信扫描二维码登录")
    @Transactional
    public Result<Map<String, String>> simulateUserScan(@RequestParam String uuid, @RequestParam String openid) {
        try {
//            logger.info("Simulate User Scan - UUID: {}, OpenID: {}", uuid, openid);
            // 检查用户是否已注册
            SysUser user = userService.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getOpenid, openid));
            if (user == null) {
                // 用户未注册，自动注册用户
                user = new SysUser();
                user.setOpenid(openid);
                user.setUsername("user_" + RandomUtil.randomString(8)); // 生成随机用户名
                String slat = RandomUtil.randomString(16); // 生成盐值
                user.setSlat(slat);
                user.setPassword(PasswordUtils.encrypt(slat, "123456")); // 设置默认密码为123456
                user.setAvatar("https://tdesign.gtimg.com/site/avatar.jpg"); // 设置默认头像
                userService.save(user);
                // 添加日志验证盐值和密码
//                System.out.println("Generated Salt: " + slat);
//                System.out.println("Generated Encrypted Password: " + user.getPassword());
            }
            // 更新二维码状态和用户ID
            redisTemplate.opsForValue().set("qrCode:" + uuid, "success", 1, TimeUnit.MINUTES);
            redisTemplate.opsForValue().set("qrCodeUserId:" + uuid, String.valueOf(user.getId()), 5, TimeUnit.MINUTES);
            // 生成 Token
            StpUtil.login(user.getId(), "wx");
            Map<String, String> map = new HashMap<>();
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            map.put("tokenHead", tokenInfo.tokenName);
            map.put("token", tokenInfo.tokenValue);
//            logger.info("Returning map: {}", map);

            return Result.success("登录成功",map);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("用户扫描处理失败");
        }
    }



    @SaIgnore
    @GetMapping("/wechatVerify")
    @Operation(summary = "微信服务器 URL 验证")
    public String wechatVerify(
            @RequestParam(name = "signature", required = true) String signature,
            @RequestParam(name = "timestamp", required = true) String timestamp,
            @RequestParam(name = "nonce", required = true) String nonce,
            @RequestParam(name = "echostr", required = true) String echostr) {
//        logger.info("Received request with signature: {}, timestamp: {}, nonce: {}, echostr: {}",
//                    signature, timestamp, nonce, echostr);

        if (signature == null || timestamp == null || nonce == null || echostr == null) {
//            logger.error("Missing required parameters");
            return "error";
        }

        // 你的 token
        String token = "mywechattoken"; // 替换为你的实际 token

        // 将 token、timestamp、nonce 三个参数进行字典序排序
        String[] arr = new String[]{token, timestamp, nonce};
        Arrays.sort(arr);

        // 将三个参数字符串拼接成一个字符串进行 sha1 加密
        StringBuilder content = new StringBuilder();
        for (String anArr : arr) {
            content.append(anArr);
        }
//        logger.info("Sorted content: {}", content.toString());

        MessageDigest md = null;
        String tmpStr = null;
        try {
            md = MessageDigest.getInstance("SHA-1");
            byte[] digest = md.digest(content.toString().getBytes());
            char[] toDigits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
            char[] str = new char[digest.length * 2];
            int i = 0;
            for (byte b : digest) {
                str[i++] = toDigits[b >>> 4 & 0xf];
                str[i++] = toDigits[b & 0xf];
            }
            tmpStr = new String(str);
//            logger.info("SHA1 result: {}", tmpStr);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return "error";
        }

        // 将 sha1 加密后的字符串可与 signature 对比，标识该请求来源于微信
        if (tmpStr != null && tmpStr.equals(signature)) {
//            logger.info("Signature matched, returning echostr: {}", echostr);
            return echostr;
        } else {
//            logger.info("Signature mismatch, expected: {}, got: {}", signature, tmpStr);
            return "error";
        }
    }


}
